package cn.zh.word.bean.service;

import cn.zh.word.bean.*;
import cn.zh.word.bean.enums.ExpectLoadCurveTypeEnum;
import cn.zh.word.bean.enums.TradeCurveTypeEnum;
import cn.zh.word.bean.mapper.EleLoadInfoMapper;
import cn.zh.word.bean.mapper.ExpectLoadCurveMapper;
import cn.zh.word.bean.mapper.TradeLoadCurveMapper;
import cn.zh.word.bean.resp.EleLoadInfoResp;
import cn.zh.word.bean.utils.DateUtil;
import cn.zh.word.utils.GenerateWordUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zh
 */
@Service
public class ScreenDailyReportServiceImpl implements ScreenDailyReportService{

    @Resource
    private TradeLoadCurveMapper tradeLoadCurveMapper;
    @Resource
    private ExpectLoadCurveMapper expectLoadCurveMapper;
    @Resource
    private EleLoadInfoMapper eleLoadInfoMapper;


    @Override
    public void create(LocalDate date, HttpServletResponse response) throws IOException {
        generateScreenReport(date, true , response.getOutputStream());
    }

    @Override
    public void update(LocalDate date) throws IOException {
        File file = new File("classpath:report" + File.separator + DateUtil.yearDateConvert(date) + "需求响应日报");
        generateScreenReport(date, true, new FileOutputStream(file));
    }

    public void generateScreenReport(LocalDate date, boolean isCreate, OutputStream outputStream) throws IOException {
        // 初始化配置
        Configure configure = GenerateWordUtils.initConfig();
        // 绑定循环表格策略
//        configure.customPolicy();eqd

        // 获取模板
        File templateFile = ResourceUtils.getFile("");
        // 编译模板
        XWPFTemplate xwpfTemplate = GenerateWordUtils.compileTemplate(templateFile, configure);
        // 模板数据
        Map<String, Object> map = new HashMap<>();
        String currDate = isCreate ? DateUtil.yearDateConvert(LocalDate.now()) : DateUtil.yearDateConvert(date.plusDays(1));
        map.put("currDate", currDate);

        // 获取用电负荷与降温负荷统计信息数据
        EleLoadInfoEO eleLoadInfoEO = new LambdaQueryChainWrapper<>(eleLoadInfoMapper)
                .eq(EleLoadInfoEO::getDate, date)
                .one();
        if (eleLoadInfoEO != null){
            EleLoadInfoResp infoResp = new EleLoadInfoResp();
            BeanUtils.copyProperties(eleLoadInfoEO, infoResp);
            infoResp.setDateStr(DateUtil.dateConvert(eleLoadInfoEO.getDate()));
            // 获取下一日最大用电负荷
            ExpectLoadCurveEO expectCurve = expectLoadCurveMapper.findByDateAndType(date, ExpectLoadCurveTypeEnum.MAX_ELE_LOAD.getCode());
            BigDecimal maxLoad = BigDecimal.valueOf(0);
            for (DateCurveDTO curveDTO : expectCurve.getCurve()){
                if (date.plusDays(1).equals(curveDTO.getDate())){
                    maxLoad = curveDTO.getValue();
                    break;
                }
            }
            infoResp.setNextDayMaxLoad(maxLoad);
            String[] split = eleLoadInfoEO.getMaxEleLoadTime().split(":");
            infoResp.setMaxEleLoadTime(split[0] + ":" + split[1]);
            infoResp.setNextDateStr(DateUtil.dateConvert(eleLoadInfoEO.getDate().plusDays(1)));
            map.put("eleLoadInfo", infoResp);
        }

        // 获取行业用电负荷数据
        ChartMultiSeriesRenderData tradeCurveData = getTradeCurveData(date);
        if (tradeCurveData != null){
            map.put("tradeCurve", tradeCurveData);
        }

        // 获取预测日曲线数据
        ChartMultiSeriesRenderData expectCurveData = getExpectLoadCurveData(date);
        if (expectCurveData != null){
            map.put("expectCurve", expectCurveData);
        }

        // 获取预测日温度曲线数据
        ChartMultiSeriesRenderData expectTempCurveData = getExpectTempCurveData(date);
        if (expectCurveData != null){
            map.put("expectTempCurve", expectCurveData);
        }

        // 填充数据
        GenerateWordUtils.fillData(xwpfTemplate, map);
        // 输出流
        GenerateWordUtils.outputWord(xwpfTemplate, outputStream);
    }

    /**
     * 获取预测日温度曲线数据
     * @param date 日期
     * @return
     */
    private ChartMultiSeriesRenderData getExpectTempCurveData(LocalDate date) {
        ExpectLoadCurveEO curveEO = expectLoadCurveMapper.findByDateAndType(date,
                ExpectLoadCurveTypeEnum.MAX_TEMP.getCode());
        if (curveEO != null){
            // x轴数据
            List<String> xData = curveEO.getCurve().stream()
                    .map(x -> {
                        LocalDate xDate = x.getDate();
                        return xDate.getMonthValue() + "月" + xDate.getDayOfMonth() + "日";
                    })
                    .collect(Collectors.toList());
            // y轴数据
            HashMap<String, List<? extends Number>> yDataMap = new HashMap<>(1);

            String type = ExpectLoadCurveTypeEnum.getByCode(curveEO.getType()).getValue();
            List<BigDecimal> yData = curveEO.getCurve().stream()
                    .map(DateCurveDTO::getValue)
                    .collect(Collectors.toList());
            yDataMap.put(type, yData);

            // 构建word图表
            return GenerateWordUtils.generateCharData("", xData, yDataMap);
        }
        return null;
    }

    /**
     * 获取预测日曲线数据
     * @param date 日期
     * @return
     */
    private ChartMultiSeriesRenderData getExpectLoadCurveData(LocalDate date) {
        List<ExpectLoadCurveEO> expectCurveList = expectLoadCurveMapper.findByDate(date);
        if (!CollectionUtils.isEmpty(expectCurveList)){
            ExpectLoadCurveEO curveEO = expectCurveList.get(0);
            // x轴数据
            List<String> xData = curveEO.getCurve().stream()
                    .map(x -> {
                        LocalDate xDate = x.getDate();
                        return xDate.getMonthValue() + "月" + xDate.getDayOfMonth() + "日";
                    })
                    .collect(Collectors.toList());
            // y轴数据
            HashMap<String, List<? extends Number>> yDataMap = new HashMap<>(expectCurveList.size());
            expectCurveList.stream()
                    .filter(x -> !ExpectLoadCurveTypeEnum.MAX_TEMP.getCode().equals(x.getType()))
                    .forEach(x->{
                        String type = ExpectLoadCurveTypeEnum.getByCode(x.getType()).getValue();
                        List<BigDecimal> yData = x.getCurve().stream()
                                .map(DateCurveDTO::getValue)
                                .collect(Collectors.toList());
                        yDataMap.put(type, yData);
            });
            // 构建word图表
            return GenerateWordUtils.generateCharData("", xData, yDataMap);
        }
        return null;
    }

    /**
     * 获取行业曲线数据
     * @param date 日期
     * @return
     */
    private ChartMultiSeriesRenderData getTradeCurveData(LocalDate date) {
        List<TradeLoadCurveEO> tradeCurveList = tradeLoadCurveMapper.findByDate(date);
        if (!CollectionUtils.isEmpty(tradeCurveList)){
            TradeLoadCurveEO curveEO = tradeCurveList.get(0);
            // x轴数据
            List<String> xData = curveEO.getCurve().stream()
                    .map(QuarterCurveDTO::getTime)
                    .collect(Collectors.toList());
            // y轴数据
            HashMap<String, List<? extends Number>> yDataMap = new HashMap<>(tradeCurveList.size());
            tradeCurveList.forEach(x->{
                String type = TradeCurveTypeEnum.getByCode(x.getType()).getValue();
                List<BigDecimal> yData = x.getCurve().stream()
                        .map(QuarterCurveDTO::getLoad)
                        .collect(Collectors.toList());
                yDataMap.put(type, yData);
            });
            // 构建word图表
            return GenerateWordUtils.generateCharData("", xData, yDataMap);
        }
        return null;
    }
}
